package net.zkbc.helloworld.repository;

import static net.zkbc.shared.util.JpaSpecUtils.eq;
import static net.zkbc.shared.util.JpaSpecUtils.like;
import static net.zkbc.shared.util.JpaSpecUtils.merge;

import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import net.zkbc.helloworld.entity.User;
import net.zkbc.helloworld.entity.User_;

public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {

	public static class DelegatingUserSpecificationExecutor {
		private UserRepository repository;

		public DelegatingUserSpecificationExecutor(UserRepository repository) {
			this.repository = repository;
		}

		public List<User> findAll(final User filter) {
			Sort sort = new Sort(new Order(Sort.Direction.DESC, User_.loginName.getName()));
			return repository.findAll(new Specification<User>() {
				@Override
				public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
					if (filter == null) {
						return cb.conjunction();
					}

					query.distinct(true);

					return cb.and(merge(

							eq(cb, root.get(User_.id), filter.getId()),
							like(cb, root.get(User_.loginName), filter.getLoginName())

					));
				}
			}, sort);
		}
	}

	public User findByLoginName(String loginName);

	@Modifying
	@Query("UPDATE User u SET u.password=:#{#user.password},salt=:#{#user.salt},loginPasswordTime=:#{#user.loginPasswordTime} WHERE u.id=:#{#user.id}")
	public void updateLoginPassword(@Param("user") User user);

}
